package mk.finki.chemistry.dice.grid;

import java.util.ArrayList;
import java.util.List;

import org.jgap.Configuration;
import org.jgap.FitnessFunction;
import org.jgap.IChromosome;
import org.jgap.Population;
import org.jgap.distr.grid.IRequestSplitStrategy;
import org.jgap.distr.grid.JGAPRequest;

/**
 * Sample implementation of IRequestSplitStrategy to split a single request
 * 
 * @author Klaus Meffert
 * @since 3.2
 */
public class MyRequestSplitStrategy implements IRequestSplitStrategy {
	/** String containing the CVS revision. Read out via reflection! */
	private final static String CVS_REVISION = "$Revision: 1.3 $";

	private Configuration m_config;

	public MyRequestSplitStrategy(Configuration a_config) {
		m_config = a_config;
	}

	public Configuration getConfiguration() {
		return m_config;
	}

	/**
	 * Creates single requests to be sent to workers. Here, each request consists
	 * of a single chromosome for which to calculate the fitness value.
	 * 
	 * @param a_request
	 *          the request to split
	 * @return single requests to be computed by workers
	 * @throws Exception
	 * 
	 * @author Klaus Meffert
	 * @since 3.2
	 */
	public JGAPRequest[] split(JGAPRequest a_request) throws Exception {
		Population pop = a_request.getPopulation();
		// Sort Population to only work with the most fittest individuals.
		// This is necessary as a Population can grow further than given
		// with the Configuration (it has to do with performance, sorry).
		// ---------------------------------------------------------------
		if (m_config.getGenerationNr() > 0) {
			// Only sort by fitness after the initial generation as in
			// generation 0 no requests have been processed on the workers.
			// ------------------------------------------------------------
			;// pop.sortByFitness();
		}

		List<IChromosome> notEvaluatedChromosomes = new ArrayList<IChromosome>();
		for (IChromosome c : pop.getChromosomes())
			if (c.getFitnessValueDirectly() == FitnessFunction.NO_FITNESS_VALUE)
				notEvaluatedChromosomes.add(c);

		if (notEvaluatedChromosomes.size() == 0)
			notEvaluatedChromosomes = pop.getChromosomes();

		JGAPRequest[] result = new JGAPRequest[notEvaluatedChromosomes.size()];
		int i = 0;
		for (IChromosome chrom : notEvaluatedChromosomes) {
			// Setup JGAP configuration for worker.
			// ------------------------------------
			Configuration config = getConfiguration().newInstance(i + "", "chromosome " + i);
			// Create single worker request.
			// -----------------------------
			result[i] = (JGAPRequest) a_request.newInstance("Chromosome " + i, i);
			result[i].setPopulation(new Population(config, chrom));
			i++;
		}
		return result;
	}
}
